home *** CD-ROM | disk | FTP | other *** search
- From: bene!luke!itkin
- Subject: head(1), and ctags(1) for AT&T type systems
- Reply-To: itkin@luke.UUCP (Steven List)
- Newsgroups: mod.sources
- Approved: jpn@panda.UUCP
-
- Mod.sources: Volume 3, Issue 87
- Submitted by: Steven List <bene!luke!itkin>
-
-
- # I've recently had the pleasure (?) of working with an AT&T
- # 3B2/300. Among the many differences I encountered are the
- # absences of the Berkeley commands head(1) and ctags(1). I'd
- # gotten used to those command due to the generosity of Plexus in
- # providing them on their System III and V systems. Needless to
- # say I immediately sat down and wrote them.
- #
- # My version of head(1) adds a command line option to the standard:
- # +n. In this case, +n means "skip n lines before displaying".
- # Yes, I'm aware that I could use sed(1) for this. But sed(1)
- # doesn't stop when it has done what you asked. It still processes
- # to the end of file. So, I figured that I'd just add this one
- # little feature.
- #
- # My version of ctags(1) is pretty much the same as the Berkeley
- # one, as far as I can tell. It uses some code to recognize
- # function declarations that I borrowed from `cpr' (I don't have
- # the original author's name). It is simple, straightforward, and
- # readily modified.
- #
- # As always, comments, changes, and corrections are welcome.
- #
- # Steven
- #
- ###
- # Steven List @ Benetics Corporation, Mt. View, CA
- # Just part of the stock at "Uncle Bene's Farm"
- # {cdp,engfocus,greipa,idi,oliveb,plx,sun,tolerant}!bene!luke!itkin
- ###
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # head.c
- # ctags.c
- # This archive created: Sat Dec 14 17:38:46 1985
- export PATH; PATH=/bin:$PATH
- echo shar: extracting "'head.c'" '(4938 characters)'
- if test -f 'head.c'
- then
- echo shar: will not over-write existing file "'head.c'"
- else
- sed 's/^ZZ//' << \SHAR_EOF > 'head.c'
- ZZ/* head - replace head command */
- ZZ/*
- ZZ * call: head [ +n ] [ -n ] [ file ... ]
- ZZ *
- ZZ * +n = number of lines to skip before starting display
- ZZ * default = 0
- ZZ * -n = number of lines to display, starting with top of file
- ZZ * default = 10
- ZZ * file = any number of files may be present
- ZZ * if name is `-', read from standard input
- ZZ */
- ZZ#include <stdio.h>
- ZZ
- ZZ#define FALSE 0
- ZZ#define TRUE 1
- ZZ
- ZZvoid dofile ();
- ZZ
- ZZmain (ac, av)
- ZZint ac;
- ZZchar **av;
- ZZ{
- ZZ register FILE *in = stdin; /* default is standard input */
- ZZ
- ZZ register int header = FALSE; /* TRUE if multiple files */
- ZZ
- ZZ register char *cp; /* general purpose pointer */
- ZZ
- ZZ register long nlines = 10; /* number of lines to display */
- ZZ register long skip = 0; /* number of lines to skip */
- ZZ
- ZZ register char *pgm; /* program name */
- ZZ
- ZZ if (pgm = strrchr (av[0], '/')) pgm++;
- ZZ else pgm = av[0];
- ZZ
- ZZ /* ------------------------------------------------------------ */
- ZZ /* Adjust args to skip program name */
- ZZ /* ------------------------------------------------------------ */
- ZZ
- ZZ av++; ac--;
- ZZ
- ZZ /* ------------------------------------------------------------ */
- ZZ /* process arguments/options */
- ZZ /* it is assumed that the options will precede all file names */
- ZZ /* on the command line */
- ZZ /* ------------------------------------------------------------ */
- ZZ
- ZZ while (ac)
- ZZ {
- ZZ if (*av[0] == '+') /* lines to skip */
- ZZ {
- ZZ skip = atoi (&av[0][1]);
- ZZ ac--; av++;
- ZZ }
- ZZ else if (*av[0] == '-') /* lines to display */
- ZZ {
- ZZ nlines = atoi (&av[0][1]);
- ZZ ac--; av++;
- ZZ }
- ZZ else break;
- ZZ }
- ZZ
- ZZ /* ------------------------------------------------------------ */
- ZZ /* If any files, then process each */
- ZZ /* ------------------------------------------------------------ */
- ZZ
- ZZ if (ac)
- ZZ {
- ZZ /* ------------------------------------------------------------ */
- ZZ /* If more than one file name specified, display headers */
- ZZ /* ------------------------------------------------------------ */
- ZZ
- ZZ header = ac > 1;
- ZZ while (ac--)
- ZZ {
- ZZ if (!strcmp (*av, "-"))
- ZZ {
- ZZ dofile (stdin, "standard input", skip, nlines, header);
- ZZ }
- ZZ else if (!(in = fopen (*av, "r")))
- ZZ {
- ZZ fprintf (stderr,
- ZZ "head: cannot read file %s - skipping\n", *av);
- ZZ }
- ZZ else
- ZZ {
- ZZ dofile (in, *av, skip, nlines, header);
- ZZ fclose (in);
- ZZ }
- ZZ av++;
- ZZ }
- ZZ }
- ZZ else dofile (stdin, "standard input", skip, nlines, FALSE);
- ZZ
- ZZ exit (0);
- ZZ}
- ZZ/* ------------------------------------------------------------ */
- ZZ/* Process a file, skipping and displaying as necessary */
- ZZ/* ------------------------------------------------------------ */
- ZZvoid
- ZZdofile (in, inname, skip, nlines, dohead)
- ZZregister FILE *in; /* input stream */
- ZZregister char *inname; /* input file name */
- ZZregister long skip; /* number of lines to skip */
- ZZregister long nlines; /* number of lines to display */
- ZZ int dohead; /* TRUE if header is to be displayed */
- ZZ{
- ZZ register char *c; /* convenient local pointer */
- ZZ register long lineno = 0; /* line number in file */
- ZZ
- ZZ char inbuf[1024]; /* line buffer */
- ZZ
- ZZ /* ------------------------------------------------------------ */
- ZZ /* Print header if necessary */
- ZZ /* ------------------------------------------------------------ */
- ZZ
- ZZ if (dohead)
- ZZ {
- ZZ printf ("\
- ZZ+-----------------------------------------------------------------+\n\
- ZZ+ %-40.40s +\n\
- ZZ+-----------------------------------------------------------------+\n",
- ZZ inname);
- ZZ }
- ZZ
- ZZ /* ------------------------------------------------------------ */
- ZZ /* Skip lines */
- ZZ /* ------------------------------------------------------------ */
- ZZ
- ZZ while (lineno++ < skip && fgets (inbuf, sizeof inbuf, in));
- ZZ
- ZZ /* ------------------------------------------------------------ */
- ZZ /* Display lines */
- ZZ /* ------------------------------------------------------------ */
- ZZ
- ZZ lineno = 0;
- ZZ
- ZZ while (lineno++ < nlines && fgets (inbuf, sizeof inbuf, in))
- ZZ fputs (inbuf, stdout);
- ZZ
- ZZ return;
- ZZ}
- SHAR_EOF
- if test 4938 -ne "`wc -c < 'head.c'`"
- then
- echo shar: error transmitting "'head.c'" '(should have been 4938 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'ctags.c'" '(6771 characters)'
- if test -f 'ctags.c'
- then
- echo shar: will not over-write existing file "'ctags.c'"
- else
- sed 's/^ZZ//' << \SHAR_EOF > 'ctags.c'
- ZZ/*T ctags - generate VI tags file from C sources */
- ZZ/*S globals and stuff */
- ZZ#include <stdio.h>
- ZZ#include <ctype.h>
- ZZ
- ZZ#define EQ ==
- ZZ#define NE !=
- ZZ#define GT >
- ZZ#define GE >=
- ZZ#define LT <
- ZZ#define LE <=
- ZZ#define OR ||
- ZZ#define AND &&
- ZZ
- ZZ#define TRUE 1
- ZZ#define FALSE 0
- ZZ
- ZZ#define SPACE ' '
- ZZ#define NUL '\0'
- ZZ
- ZZtypedef short BOOL;
- ZZ
- ZZchar FunctionName[40];
- ZZ
- ZZchar *ReservedWord[] = {
- ZZ "BOOL", "auto", "bool", "break", "case", "char", "continue",
- ZZ "default", "do", "double", "else", "entry", "enum",
- ZZ "extern", "float", "for", "goto", "if",
- ZZ "int", "long", "register", "return", "short",
- ZZ "sizeof", "static", "struct", "switch",
- ZZ "typedef", "union", "unsigned", "void", "while",
- ZZ NULL };
- ZZ
- ZZchar *pgm;
- ZZchar inbuf[512];
- ZZ
- ZZextern char *strchr (); /* index on BSD */
- ZZextern char *strrchr (); /* rindex on BSD */
- ZZextern char *strpbrk (); /* ??? */
- ZZ
- ZZint skiptoend (); /* skip to end of function */
- ZZchar ckfunc (); /* check for function declaration */
- ZZ/*Page Eject*/
- ZZmain (ac, av)
- ZZint ac;
- ZZchar *av[];
- ZZ{
- ZZ register FILE *in; /* input file stream */
- ZZ register FILE *tagfile; /* `tags' file being created */
- ZZ
- ZZ register char *cp; /* convenient character pointers */
- ZZ register char *ep; /* */
- ZZ
- ZZ register int i; /* loop index and such */
- ZZ register int index = FALSE; /* if true, produce a functions */
- ZZ /* index instead of tags file */
- ZZ register int line_number = 0; /* line number of declaration */
- ZZ register int optind = 1; /* like getopt - command arg */
- ZZ
- ZZ char *funcname; /* function name */
- ZZ
- ZZ char filename[15]; /* like it says */
- ZZ
- ZZ if (pgm = strrchr (av[0], '/')) pgm++;
- ZZ else pgm = av[0];
- ZZ
- ZZ /* ------------------------------------------------------------ */
- ZZ /* Create the tags file */
- ZZ /* ------------------------------------------------------------ */
- ZZ
- ZZ tagfile = fopen ("tags", "w");
- ZZ if (!tagfile)
- ZZ {
- ZZ perror ("tags");
- ZZ fprintf (stderr,
- ZZ "%s: cannot create file tags\n", pgm);
- ZZ exit (1);
- ZZ }
- ZZ
- ZZ /* ------------------------------------------------------------ */
- ZZ /* If selected, write a function index to stdout instead */
- ZZ /* ------------------------------------------------------------ */
- ZZ
- ZZ if (!strncmp (av[1], "-x", 2))
- ZZ {
- ZZ index = TRUE;
- ZZ optind++;
- ZZ }
- ZZ
- ZZ /* ------------------------------------------------------------ */
- ZZ /* Process each file specified on the command line */
- ZZ /* ------------------------------------------------------------ */
- ZZ
- ZZ for (i = optind; i LT ac; i++)
- ZZ {
- ZZ if (!(in = fopen (av[i], "r")))
- ZZ {
- ZZ perror (av[i]);
- ZZ fprintf (stderr,
- ZZ "%s: unable to read file %s\n", pgm, av[i]);
- ZZ }
- ZZ else
- ZZ {
- ZZ while (fgets (inbuf, sizeof inbuf, in))
- ZZ {
- ZZ line_number++;
- ZZ if (ckfunc (inbuf))
- ZZ {
- ZZ /* ------------------------------------------------------------ */
- ZZ /* Found a function declaration */
- ZZ /* ------------------------------------------------------------ */
- ZZ
- ZZ inbuf[strlen(inbuf)-1] = NUL;
- ZZ if (index)
- ZZ {
- ZZ printf ("%-20.20s %6d %s\t%s\n",
- ZZ FunctionName, line_number, av[i], inbuf);
- ZZ }
- ZZ /* ------------------------------------------------------------ */
- ZZ /* Special case function name `main' */
- ZZ /* ------------------------------------------------------------ */
- ZZ else if (!strcmp (FunctionName, "main"))
- ZZ {
- ZZ cp = strrchr (av[i], '/');
- ZZ if (cp) cp++;
- ZZ else cp = av[i];
- ZZ strcpy (filename, cp);
- ZZ ep = strrchr (filename, '.');
- ZZ if (ep) *ep = NUL;
- ZZ fprintf (tagfile, "M%s\t%s\t?^%s$?\n",
- ZZ filename, av[i], inbuf);
- ZZ }
- ZZ else
- ZZ {
- ZZ fprintf (tagfile, "%s\t%s\t?^%s$?\n",
- ZZ FunctionName, av[i], inbuf);
- ZZ }
- ZZ line_number += skiptoend (in);
- ZZ }
- ZZ }
- ZZ fclose (in);
- ZZ }
- ZZ }
- ZZ fclose (tagfile);
- ZZ
- ZZ /* ------------------------------------------------------------ */
- ZZ /* Tags file must be sorted alphabetically on tag */
- ZZ /* ------------------------------------------------------------ */
- ZZ
- ZZ system ("sort -u -t'\t' +0 -1 -o tags tags");
- ZZ
- ZZ exit (0);
- ZZ}
- ZZ/*S ckfunc - check line for function declaration */
- ZZ/*H ckfunc */
- ZZ/*E*/
- ZZ
- ZZ#define isidchr(c) (isalnum(c) OR (c EQ '_'))
- ZZ
- ZZchar
- ZZckfunc (s)
- ZZregister char *s; /* string to check for declaration */
- ZZ{
- ZZ register char *p; /* convenient character pointer */
- ZZ register int i; /* useful loop index */
- ZZ register int result; /* used to terminate search loop */
- ZZ register char found = FALSE; /* true if declaration found */
- ZZ
- ZZ static char *_fnm = "ckfunc";
- ZZ
- ZZ /* ------------------------------------------------------------ */
- ZZ /* There's GOT to be a left paren for there to be a declaration */
- ZZ /* ------------------------------------------------------------ */
- ZZ
- ZZ if (strchr (s, '('))
- ZZ {
- ZZ found = TRUE;
- ZZ
- ZZ while (found)
- ZZ {
- ZZ found = FALSE;
- ZZ p = FunctionName;
- ZZ for (s; isascii (*s) AND isspace (*s) AND *s; s++);
- ZZ if( *s EQ '*' )
- ZZ {
- ZZ for (++s; isascii (*s) AND isspace (*s) AND *s; s++);
- ZZ }
- ZZ
- ZZ if ((*s EQ '_') OR isalpha(*s))
- ZZ {
- ZZ while (isidchr (*s)) *p++ = *s++;
- ZZ
- ZZ *p = NUL;
- ZZ
- ZZ for (found = FALSE, i = 0;
- ZZ !found AND ReservedWord[i]; i++)
- ZZ {
- ZZ if (!(result = strcmp (FunctionName, ReservedWord[i])))
- ZZ found = TRUE;
- ZZ else if (result LT 0) break;
- ZZ }
- ZZ }
- ZZ }
- ZZ }
- ZZ
- ZZ for (s; isascii (*s) AND isspace (*s) AND *s; s++);
- ZZ
- ZZ if (*s EQ '(')
- ZZ {
- ZZ for (found = FALSE; *s AND !found; s++)
- ZZ found = *s EQ ')';
- ZZ
- ZZ if (found)
- ZZ {
- ZZ for (; *s AND isspace (*s); s++);
- ZZ
- ZZ found = *s NE ';';
- ZZ }
- ZZ }
- ZZ
- ZZ return found;
- ZZ}
- ZZ/* ------------------------------------------------------------ */
- ZZ/* Skiptoend is called after a function declaration is found */
- ZZ/* to skip to the end of the function. */
- ZZ/* ------------------------------------------------------------ */
- ZZint
- ZZskiptoend (in)
- ZZregister FILE *in; /* file being processed */
- ZZ{
- ZZ register int nest = 0; /* nesting level - zero means end */
- ZZ register int c; /* character being checked */
- ZZ register int line_number = 0; /* like it says */
- ZZ
- ZZ /* ------------------------------------------------------------ */
- ZZ /* Simpleminded search for the starting brace */
- ZZ /* ------------------------------------------------------------ */
- ZZ
- ZZ while (((c = getc (in)) NE EOF) AND c NE '{')
- ZZ if (c EQ '\n') line_number++;
- ZZ
- ZZ nest++;
- ZZ
- ZZ /* ------------------------------------------------------------ */
- ZZ /* Keep going until the paired brace is found */
- ZZ /* ------------------------------------------------------------ */
- ZZ
- ZZ while (nest AND ((c = getc (in)) NE EOF))
- ZZ {
- ZZ switch (c)
- ZZ {
- ZZ case '{': nest++; break;
- ZZ case '}': nest--; break;
- ZZ case '\n': line_number++;
- ZZ }
- ZZ }
- ZZ
- ZZ return line_number;
- ZZ}
- SHAR_EOF
- if test 6771 -ne "`wc -c < 'ctags.c'`"
- then
- echo shar: error transmitting "'ctags.c'" '(should have been 6771 characters)'
- fi
- fi # end of overwriting check
- # End of shell archive
- exit 0
-
-
-
-